﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Expression.Controls;
using StrategyMap.UserControls;
using System.Windows.Interactivity;
using BSCMFF.Core.DataAccessLayer;
using System.ServiceModel.DomainServices.Client;
using BSCMFF.Web.DomainService;
using Microsoft.Expression.Media;

namespace StrategyMap
{
    public partial class TestMap : UserControl
    {
        public event EventHandler EventLineArrowCreated;
        public event EventHandler EventNodeClicked;

		public TestMap()
		{
			// Required to initialize variables
			InitializeComponent();

           // LoadNodesAndArrows(this, new RoutedEventArgs());


		}
		
		//private List<Node1> nodes;
        //private List<LineArrow> arrows;

        #region LoadNodesAndArrows

        private readonly StrategyMapDomainContext strategyContext = new StrategyMapDomainContext();
        private LoadOperation<Strategy_Node> loadOpNodes;
        private LoadOperation<Strategy_Arrow> loadOpArrows;

        private List<Node1> nodes1 = new List<Node1>();

        public void LoadNodesAndArrows(object sender, RoutedEventArgs e)
        {
            //bi.IsBusy = true;
            try
            {
                loadOpNodes = strategyContext.Load(strategyContext.GetStrategy_NodeQuery());
                //loadOpArrows = strategyContext.Load(strategyContext.GetStrategy_ArrowQuery());

                //chyba.Text += "preslo";
            }
            catch 
            {
                //chyba.Text += "nepreslo";
            }


            loadOpNodes.Completed += new EventHandler(LoadOpNodes_Completed);
        }

        public void LoadOpNodes_Completed(object sender, EventArgs e)
        {
            //List<Strategy_Node> nodes = loadOpNodes.Entities.ToList();
            //chyba.Text += nodes.Count.ToString();

            AddNodesIntoStrategyMap();
			
			loadOpArrows = strategyContext.Load(strategyContext.GetStrategy_ArrowQuery());
            loadOpArrows.Completed += new EventHandler(LoadOpArrows_Completed);
        }

        public void LoadOpArrows_Completed(object sender, EventArgs e)
        {
            //chyba.Text += " arrowscompleted";
            foreach (Strategy_Arrow sn in loadOpArrows.Entities)
            {
                ConnectBehavior cb = new ConnectBehavior();
                cb.ConnectTo = sn.Strategy_Node_To_FK.ToString();

                Node1 from = nodes1.First(n1 => n1.Name == sn.Strategy_Node_From_FK.ToString()); //(Node1)LayoutRoot.FindName(sn.Strategy_Node_From_FK.ToString());
                Node1 to = nodes1.First(n1 => n1.Name == sn.Strategy_Node_To_FK.ToString()); //(Node1)LayoutRoot.FindName(sn.Strategy_Node_To_FK.ToString());

                Interaction.GetBehaviors(from).Add(cb);
                Interaction.GetBehaviors(to).Add(new ConnectBehavior());

                LineArrow la = Connections.Add(from, to, adjustOnly: false);
                SetLineArrowDataContext(la, sn);
                Connections.Adjust(from, to);
            }
            //bi.IsBusy = false;            
        }

        //save
        private void ButtonSaveNodes_Click(object sender, RoutedEventArgs e)
        {
            //tb.Text = "from " + GetLeftCoord(from) + " " + GetTopCoord(from) ;

            foreach (Strategy_Node sn in strategyContext.Strategy_Nodes)
            {
                // Node1 node = (Node1)LayoutRoot.FindName(sn.Strategy_Node_ID.ToString());
                Node1 node1 = nodes1.First(n1 => n1.Name == sn.Strategy_Node_ID.ToString());
                if (node1 != null)
                {
                    sn.CoordX = Convert.ToInt32(GetLeftCoord(node1));
                    sn.CoordY = Convert.ToInt32(GetTopCoord(node1));
                }
            }

            strategyContext.SubmitChanges();

            //loadOp = strategyContext.Load(strategyContext.GetStrategy_NodeQuery());

            //loadOp.Completed += new EventHandler(LoadOp_Completed_Save);
        }

        #endregion

        private Node1 NodeDrawingArrowFrom;
        //private Line nepouzivana;
        //private LineArrow la;

        void Node_StartDrawingArrowEvent(object sender, MouseButtonEventArgs e)
        {
            CreateTemporaryArrow(e);
            NodeDrawingArrowFrom = (Node1)sender;
            NodeTargetSelection();            
        }
        
        private void NodeTargetSelection()
        {
            ///add mouseenter/leave and leftbuttonup events
            AddTargetEventsForNodes();

            /// line will follow mouse point
            LayoutRoot.MouseMove += new MouseEventHandler(LayoutRoot_MouseMove);

            /// when we finish line oudside any node
            LayoutRoot.MouseLeftButtonUp += new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonUp);
        }

        

        void Node_MouseEnter(object sender, MouseEventArgs e)
        {
            Node1 n = (Node1)sender;
            n.Main.Stroke = new SolidColorBrush(Colors.Red);


            n.NodeTargetEntered = true;
            //n.MouseLeave += new MouseEventHandler(Node_MouseLeave);
        }

        void Node_MouseLeave(object sender, MouseEventArgs e)
        {
            Node1 n = (Node1)sender;
            n.Main.Stroke = new SolidColorBrush(Colors.Black);
            n.NodeLayoutRoot.Background = new SolidColorBrush(Colors.Transparent);
            n.NodeTargetEntered = false;
        }

        void Node_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Node1 nodeTarget = (Node1)sender;

            if (nodeTarget.NodeTargetEntered)
            {
                LayoutRoot.Children.Remove(la);
                //tb.Text += "create arrow";
            }

            foreach(Node1 n1 in nodes1)
            {
                n1.MouseEnter -= Node_MouseEnter;
                n1.MouseLeave -= Node_MouseLeave;
                n1.MouseLeftButtonUp -= Node_MouseLeftButtonUp;
                n1.Main.Stroke = new SolidColorBrush(Colors.Black);
                n1.NodeLayoutRoot.Background = new SolidColorBrush(Colors.Transparent);
            }
            
            NodeDrawingArrowFrom.AttachDragBehavior();
            
            LayoutRoot.MouseLeftButtonUp -= LayoutRoot_MouseLeftButtonUp;
            CreatePermanentArrow(NodeDrawingArrowFrom, nodeTarget);
        }

        
        private void CreatePermanentArrow(Node1 NodeDrawingArrowFrom, Node1 nodeTarget)
        {
            ConnectBehavior cb = new ConnectBehavior();
            cb.ConnectTo = nodeTarget.Name;

            Interaction.GetBehaviors(NodeDrawingArrowFrom).Add(cb);
            Interaction.GetBehaviors(nodeTarget).Add(new ConnectBehavior());

            LineArrow la = Connections.Add(NodeDrawingArrowFrom, nodeTarget, adjustOnly: false);
            SetLineArrowDataContext(la, null);

            if (EventLineArrowCreated != null)
            {
                EventLineArrowCreated(la, new EventArgs());
            }

            Connections.Adjust(NodeDrawingArrowFrom, nodeTarget);
        }

        private void SetLineArrowDataContext(LineArrow la, Strategy_Arrow arrow)
        {
            if (la != null)
            {
                la.MouseLeftButtonDown += new MouseButtonEventHandler(la_MouseLeftButtonDown);
                la.Name = arrow == null ? "meno" : arrow.Name;
                la.DataContext = arrow == null ? "tralala" : arrow.Description;
            }
        }

        public event EventHandler EventLineArrowLeftButtonDown;
        void la_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (EventLineArrowLeftButtonDown != null)
            {
                EventLineArrowLeftButtonDown(sender, new EventArgs());
            }
        }

        void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            LayoutRoot.Children.Remove(la);
            NodeDrawingArrowFrom.AttachDragBehavior();
            //tb.Text += "layout up";
            foreach (Node1 n1 in nodes1)
            {
                n1.MouseEnter -= Node_MouseEnter;
                n1.MouseLeave -= Node_MouseLeave;
                n1.MouseLeftButtonUp -= Node_MouseLeftButtonUp;
            }
            LayoutRoot.MouseLeftButtonUp -= LayoutRoot_MouseLeftButtonUp;
        }

        
        //public void LoadOp_Completed_Save(object sender, EventArgs e)
        //{
        //    //strategyContext.Strategy_Nodes
        //    foreach (Strategy_Node sn in loadOpNodes.Entities)
        //    {
        //        Node1 n = (Node1)LayoutRoot.FindName(sn.Strategy_Node_ID.ToString());
        //        sn.CoordX = Convert.ToInt32(Leftt(n));
        //        sn.CoordY = Convert.ToInt32(Topp(n));

        //    }

        //    strategyContext.SubmitChanges();
        //}




        #region Coordinates

        private LineArrow la;

        private const int fromMouse = 5;

        void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
        {
            Point coordinate = new Point();

            coordinate = e.GetPosition(null);

            

            double difx, dify;
            difx = coordinate.X - pFrom.X;
            dify = coordinate.Y - pFrom.Y;

            if (difx > 0)
            {
                if (dify > 0)
                {
                    difx -= fromMouse; difx = difx < 0 ? 0 : difx;
                    dify -= fromMouse; dify = dify < 0 ? 0 : dify;
                    la.Width = difx;
                    la.Height = dify;
                    la.StartCorner = CornerType.TopLeft;

                }
                else
                {
                    difx -= fromMouse; difx = difx < 0 ? 0 : difx;
                    dify += fromMouse; dify = dify > 0 ? 0 : dify;

                    la.Width = difx;
                    la.Height = -dify;
                    la.StartCorner = CornerType.BottomLeft;
                    Canvas.SetTop(la, pFrom.Y + dify);
                }
            }
            else
            {
                if (dify > 0)
                {
                    difx += fromMouse; difx = difx > 0 ? 0 : difx;
                    dify -= fromMouse; dify = dify < 0 ? 0 : dify;

                    la.Width = -difx;
                    la.Height = dify;
                    //la.StartArrow = (ArrowType)CornerType.TopRight;
                    la.StartCorner = CornerType.TopRight;

                    Canvas.SetLeft(la, pFrom.X + difx);
                }
                else
                {
                    difx += fromMouse; difx = difx > 0 ? 0 : difx;
                    dify += fromMouse; dify = dify > 0 ? 0 : dify;

                    la.Width = -difx;
                    la.Height = -dify;

                    la.StartCorner = CornerType.BottomRight;
                    Canvas.SetLeft(la, pFrom.X + difx);
                    Canvas.SetTop(la, pFrom.Y + dify);
                }
            }


        }

        public double GetLeftCoord(Object value)
        {
            if (value.GetType() == typeof(Canvas))
            {
                var g = ((UIElement)value).TransformToVisual(Application.Current.RootVisual);
                var offset = g.Transform(new Point(0, 0));
                return offset.X;
            }
            else
            {
                var g = ((UserControl)value).TransformToVisual(LayoutRoot);
                var offset = g.Transform(new Point(0, 0));
                return offset.X;// -320;
            }
        }

        public double GetTopCoord(Object value)
        {
            if (value.GetType() == typeof(Canvas))
            {
                var g = ((UIElement)value).TransformToVisual(Application.Current.RootVisual);
                var offset = g.Transform(new Point(0, 0));
                return offset.Y;
            }
            else
            {
                var g = ((UserControl)value).TransformToVisual(LayoutRoot);
                var offset = g.Transform(new Point(0, 0));
                return offset.Y;// -166;
            }
        }

        #endregion
    }
}
